package com.assignwork.service.impl;

import com.assignwork.dto.StatisticsThroughputForecastCargoDTO;
import com.assignwork.dto.ThroughputForecastDTO;
import com.assignwork.entity.ThroughputForecast;
import com.assignwork.entity.ThroughputForecastItem;
import com.assignwork.mapper.ThroughputForecastMapper;
import com.assignwork.service.IThroughputForecastItemService;
import com.assignwork.service.IThroughputForecastService;
import com.assignwork.vo.StatisticsThroughputForecastVO;
import com.assignwork.vo.ThroughputForecastOreVO;
import com.assignwork.vo.ThroughputForecastVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.AllArgsConstructor;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.tool.utils.Func;
import org.springblade.system.cache.DictBizCache;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.Year;
import java.util.*;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class ThroughputForecastServiceImpl extends BaseServiceImpl<ThroughputForecastMapper, ThroughputForecast> implements IThroughputForecastService {

    IThroughputForecastItemService itemService;

    @Override
    public IPage<ThroughputForecastVO> pageThroughputForecast(BladeUser bladeUser, IPage<ThroughputForecastVO> page, ThroughputForecastDTO dto) {
        IPage<ThroughputForecastVO> res = baseMapper.pageThroughputForecastVO(page, dto);
        for (ThroughputForecastVO vo : res.getRecords()) {
            vo.setImpExpName(DictBizCache.getValue(ThroughputForecastDTO.I_E_TYPE, vo.getImpExp()));
            vo.setTradeTypeName(DictBizCache.getValue(ThroughputForecastDTO.TRADE_TYPE, vo.getTradeType()));
            vo.setShipBerthName(DictBizCache.getValue(ThroughputForecastDTO.BERTH, vo.getShipBerthKey()));
        }
        return res;
    }

    @Override
    public List<StatisticsThroughputForecastVO> statisticsThroughputForecast(BladeUser bladeUser, IPage<StatisticsThroughputForecastVO> page, ThroughputForecastDTO dto) {
        List<StatisticsThroughputForecastVO> records = baseMapper.statisticsThroughputForecast( dto);

        for (StatisticsThroughputForecastVO record : records) {
            if (dto.getStatisticsType().equals("month") || dto.getStatisticsType().equals("periodTenDays")) {
                record.setPeriodTenDaysName(DictBizCache.getValue(ThroughputForecastDTO.PERIOD_TEN_DAYS, record.getPeriodTenDays()));
            }
        }

        if (dto.getStatisticsType().equals("periodTenDays")) {
            List<StatisticsThroughputForecastVO> ls = new ArrayList<>();
            Map<String, List<StatisticsThroughputForecastVO>> collect = records.stream().collect(Collectors.groupingBy(StatisticsThroughputForecastVO::getEndTime));
            for (Map.Entry<String, List<StatisticsThroughputForecastVO>> entry : collect.entrySet()) {
                List<StatisticsThroughputForecastVO> value = entry.getValue();
                if (Func.isNotEmpty(value)) {
                    value.sort((a, b) -> {
                        return Func.toInt(a.getPeriodTenDays(), 0) - Func.toInt(b.getPeriodTenDays(), 0);
                    });
                }
                BigDecimal iTon = value.stream().map(StatisticsThroughputForecastVO::getITon).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal iiTon = value.stream().map(StatisticsThroughputForecastVO::getIiTon).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal ieTon = value.stream().map(StatisticsThroughputForecastVO::getIeTon).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal oTon = value.stream().map(StatisticsThroughputForecastVO::getOTon).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal oiTon = value.stream().map(StatisticsThroughputForecastVO::getOiTon).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal oeTon = value.stream().map(StatisticsThroughputForecastVO::getOeTon).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal totalTon = value.stream().map(StatisticsThroughputForecastVO::getTotalTon).reduce(BigDecimal.ZERO, BigDecimal::add);
                ls.add(new StatisticsThroughputForecastVO() {{
                    setITon(iTon);
                    setIiTon(iiTon);
                    setIeTon(ieTon);
                    setOTon(oTon);
                    setOiTon(oiTon);
                    setOeTon(oeTon);
                    setTotalTon(totalTon);
                    setEndTime(entry.getKey());
                    setSubset(value);
                }});
            }
            records = ls;
        }

        records.sort((a, b) -> {
            int aa = 0;
            int bb = 0;
            if (Func.isNotBlank(a.getEndTime())) {
                aa = Func.toInt(a.getEndTime().replaceAll("-", ""), 0);
            }
            if (Func.isNotBlank(b.getEndTime())) {
                bb = Func.toInt(b.getEndTime().replaceAll("-", ""), 0);
            }
            return aa - bb;
        });
        return records;
    }

    @Override
    public String statisticsAllThroughputForecast(BladeUser bladeUser, ThroughputForecastDTO dto) {
        return baseMapper.statisticsAllThroughputForecast(dto);
    }

    @Override
    public List<Map<String, String>> statisticsThroughputForecastCargo(BladeUser bladeUser, Long groupId, String year) {
        List<StatisticsThroughputForecastCargoDTO> dtos = baseMapper.statisticsThroughputForecastCargo(groupId, year);
        return StatisticsThroughputForecastCargoDTO.getData(dtos);
    }

    @Override
    public boolean saveOrUpdateDTO(ThroughputForecastDTO dto) {
        if (dto.getId() != null) {
            this.itemService.remove(
                    new QueryWrapper<ThroughputForecastItem>()
                            .lambda()
                            .eq(ThroughputForecastItem::getParentId, dto.getId())
            );
        }
        this.saveOrUpdate(dto);
        return this.itemService.saveOrUpdateBatch(dto.getCargoTonEtt());
    }

}
